package com.niit.base

import scala.collection.mutable.ListBuffer

object Base_08 {

  def main(args: Array[String]): Unit = {
    /*
     元组：长度和元素都是不可变的
     */
    //定义元组 ，访问元组
    var tuple1 = ("张三","李四","王五")
    var tuple2 ="张三" -> 23 -> '男'  //((张三,23),男)
    println(tuple1._1)
    println(tuple2._2)
    //元组遍历 先让元组生成一个迭代器，在利用这个迭代器进行遍历
    val iterator = tuple1.productIterator
    for (i <- iterator){//i 表示元组中每一个元素
      println(i)
    }

    /*
      列表  有序 可重复
        不可变列表
        可变列表
        列表基础操作
        列表的扁平化
        列表的拉链与拉开
     */
    //不可变列表
    var list1 = List(1,2,3,4,5)
    //创建一个不可变的空列表
    var list2 = Nil
    var list3 = 2 :: 1 ::Nil
    println(list1)
    println(list2)
    println(list3)
    //可变列表
    import scala.collection.mutable.ListBuffer
    var list4 = ListBuffer[Int]()
    var list5 = ListBuffer(1,2,3,4,5)
    println(list5(2))
    list4 ++= List(3,1,2,4,5)
    //变成一个数组
    val array = list4.toArray
    //变成一个不可变列表
    val list = list4.toList
    //数组的常用操作
    //获得列表中的第一个元素
    val head = list5.head
    //获得列表中除第一个元素外的其他元素
    val tail = list5.tail
    //获得列表中前几个元素
    val value = list5.take(3)
    //获得列表中后几个元素
    val value1 = list5.drop(3)

    //列表的扁平化：将嵌套在列表中的所有子列表中的所有元素都独立到一个新列表当中
    var list6 = List(List(1,2),List(3,4),List(5))
    val flatten = list6.flatten //List(1, 2, 3, 4, 5)
    println(flatten)

    //列表的 拉链与拉开
    //拉链:将两个列表，组合成一个元素为元组的列表
    val names = List("张三","李四","王五")
    val ages = List(23,24,25)
    val value2 = names.zip(ages);
    println(value2) //List((张三,23), (李四,24), (王五,25))
    //拉开:将一个包含元组的列表，拆解成包含两个列表的元组
    val unzip = value2.unzip
    println(unzip)//  (List(张三, 李四, 王五),List(23, 24, 25))


    /*
    集合： 没有重复的元素，唯一 无序
    不可变集
    可变集
     */
    //不可变集 元素和长度都是不可变的
    var set1 = Set[Int]()
    var set2 = Set(1,2,3,2,3,1)
    println(set2)
    for (i <- set2 ) println(i)
    //可变集
    import scala.collection.mutable.Set
    var set3 = Set(1,2,3,4)
    set3 += 5
    set3 ++= List(5,6,7,8,9)
    println(set3)

    /*映射 -> 字典 -> Map -> 键值对
      不可变Map
      可变Map
      Map的基本操作
    */
    //不可变Map
    var map1 = Map("张三"->23,"李四"->24,"王五"->25)
    var map2 = Map(("张三",23),("李四",24),("王五",25))
    println(map2)
    //可变Map
    // import scala.collection.mutable.Map
    var map3 = Map(("张三",23),("李四",24),("王五",25))
    //map3("张三") = 40
    println(map3)
    //基础操作
   // println(map3("赵六")) // key不存在的异常
    println(map3.get("赵六"))  // None
    //获得所有键
    println(map3.keys)
    //获得所有值
    println(map3.values)
    //遍历
    for ((k,v) <- map3){
      println(k,v)
    }
    //获取一个不存在的键，并返回指定数据
    println( map3.getOrElse("赵六",-1))

    /*
    迭代器 ：针对每一类的集合 都会有一个迭代器，用来迭代访问结合
      hasNext:查询容器中是否含有下一个元素
      neXt:返回迭代器中的下一个元素。如果没有就抛异常
     */
    var list7 = List(1,2,3,4,5,6,7)
    val iterator1 = list7.iterator
    while (iterator1.hasNext){
      println(iterator1.next())
    }

    /*
    函数式编程
        函数式编程指 方法的参数列表可以接收函数对象。
     */
    //foreach 可以代码看起来更简洁 优雅
    var list9 = List(1,2,3,4,5,6)
    list9.foreach( (i:Int) => println(i)  )
    //升级版
    list9.foreach( i => println(i)  )
    //究极版  _:就是表示 你要循环的每一个元素
    list9.foreach(println(_))

    //map:将一种数据类型 转换为 另外一种数据类型 ，以新的列表去接收
    // 需求：电影打分系统，分为4个等级 1，2，3，4。但是用户必须以 * 的方式进行打分
    var list10 = List(1,2,3,4)
    //初级版
     var ll1 =  list10.map((i:Int) => "*" * i)
     println(ll1)
    //升级版
    var ll2 =  list10.map( i => "*" * i)
    println(ll2)
    //究极版
    var ll3 =  list10.map( "*" * _)
    println(ll3)

    /*flatMap 扁平化映射 *
    扁平化：将一个列表中的所有子列表独立成一个新列表 ( ( 1,2),(3,4),(5,6) )  => (1,2,3,4,5,6)
     先Map => 将列列表中的元素都转换一个List
     再 flatten :将整个列表进行扁平化
     */
    //( "C HTML-CSS Java MySQL"  , "Python Hadoop Hbase Spark Scala" )
    // => （C ,HTML-CSS,Java ,MySQL …………………………）
    var list11 = List( "C HTML-CSS Java MySQL"  , "Python Hadoop Hbase Spark Scala" )
    //传统方式：
    //1.得每一个数组，并以空格进行切割
      var ll4 = list11.map(_.split(" ")) // ( [C,HTML-CSS,Java,mMySQL],[Python,Hadoop,Hbase,Spark,Scala]  )
    //2.进行扁平化
     var ll5 =  ll4.flatten
     println(ll5)
    //函数式：
    /*
     先Map => 将列列表中的元素都转换一个List
     再 flatten :将整个列表进行扁平化
     */
    var ll6 = list11.flatMap(_.split(" "))
    println(ll6)

    //filter过滤： 过滤出符合一定条件元素,返回一个新列表
    // 1 to 9 生成的是 1-的数组
    var list12 = (1 to 9).toList
    //过滤出可以被2整除数据  _：就是列表中每一个元素
    var ll7 = list12.filter(_%2==0)
    println(ll7)

    /*排序
    *  sorted:对集合进行默认排序
    *  sortBy：对集合进行指定字段排序
    *  sortWith:对集合进行自定义排序
    * */
    //sorted
    var list13 = List(3,1,2,4,5,9,7)
    var ll8 = list13.sorted //返回一个排序后列表
    println(ll8)
    //sortBy
    var list14 =List("01 hadoop","02 flume","03 spark","04 kafka")
    //根据字母顺序进行排序
    var ll9 =  list14.sortBy(x => x.split(" ")(1))//[01,hadoop]
    println(ll9)
    //究极版
    var ll10 = list14.sortBy(_.split(" ")(1))
    println(ll10)
    //sortWith自定排序
    var list15 = List(2,3,1,6,4,5)
    //使用sortWith降序
    var ll11 = list15.sortWith((x,y) => x > y)
    println(ll11)
    //究极版
    var ll12 = list15.sortWith( _ > _ )  //sortWith需要有两个值 x ,y 大家已经知道了两个值了，所以要简化了 就 第一个_表示x  第二个 _表示y
    println(ll12)

    //groupBy 分组。将数组按照指定条件进行分组
    /*1.对一个班里面的学生按照性别进行分组
      2.统计不同性别的学生人数
     */
    var list16 = List("刘德华"->"男","范冰冰"->"女","胡歌"->"男")
    var ll13 =  list16.groupBy(x => x._2) //返回值是一个Map
    println(ll13)
    var ll14 = list16.groupBy(_._2)
    println(ll14)
    //统计不同性别的学生人数  HashMap(  男 -> List((刘德华,男), (胡歌,男)),      女 -> List((范冰冰,女))   )
    var ll15 = ll14.map(x => x._1 -> x._2.size)//这里x不能用下划线去替代，因为后面出现了2次
    println(ll15)
    /*
    聚合操作：将一个列表中的数据合并为一个
      reduce:用来对集合元素进行聚合计算
      fold:用来对集合进行折叠计算
     */
    /*

      reduce == reduceLeft:从左向右进行计算
      reduceRight：从右向左进行计算
     */
    var list17 = (1 to 10).toList
    //使用reduce进行累加
    var ll16 = list17.reduce(_+_) //x :_   y:_
    println(ll16)
    val ll17 = list17.reduceRight(_ + _)
    println(ll17)

    /*
    flod：将一个列表中的数据合并为一个列表，多了一个初始值
     flod == flodLeft:从左向右进行计算
      flodRight：从右向左进行计算
     */
    var list18 = (1 to 10).toList
    val ll18 = list18.fold(100)(_+_)// 100 +1+2+3+4+5+6+7+8+9+10
    println(ll18)

}

}
